/**
 * 将视频从一种格式转换为另一种格式，如 .ts 转 .mp4、1080P 转 720P。
 *
 * ```shell
 * # 转换目录下的所有 ts 视频为 720P 的 mp4 格式：
 * $ deno run --allow-run --allow-read --allow-write src/convert.js -i temp -s=-2:720 -t ts:mp4 -o temp/converted
 * ```
 *
 * 命令行参数说明：
 * 1. -i : 要转换的视频所在目录，默认为当前目录。
 * 2. -s : 转换后的分辨率，如 "-2:720" 代表转换为 720P，不设置代表保留原始视频分辨率。
 * 3. -c : 是否添加 "-c copy" 参数给 ffmpeg，添加此参数后将直接复制视频而不重新转码。
 * 4. -t : 转换的格式配置，默认为 "ts:mp4"，代表将 `.ts` 视频转换为 `.mp4` 格式。
 * 5. -o : 转换后的视频文件所保存的目录，默认 -i 值指定的目录下的子目录 converted。
 */

import { parse } from "/deno.land/std/flags/mod.ts";
import * as path from "/deno.land/std/path/mod.ts";
import { exists } from "./share/file.js";
import { log } from "./share/common.js";
import { ffmpeg } from "./share/ffmpeg.js";

// 解析命令行参数
const parsedArgs = parse(Deno.args);

// 构建 ffmpeg 参数
const ffmpegArgs1 = { "-strict": "strict" };
const ffmpegArgs2 = {};
// 分辨率配置
if (Object.hasOwn(parsedArgs, "s")) ffmpegArgs2["-vf"] = `scale=${parsedArgs["s"]}`;
// 如果有 -y -n --vf 等自定义的参数也添加进去，方便自定义额外的 ffmpeg 参数
if (Object.hasOwn(parsedArgs, "y")) ffmpegArgs2["-y"] = true;
if (Object.hasOwn(parsedArgs, "n")) ffmpegArgs2["-n"] = true;
if (Object.hasOwn(parsedArgs, "c")) ffmpegArgs2["-c"] = "copy";
if (Object.hasOwn(parsedArgs, "vf")) {
  ffmpegArgs2["-vf"] = Object.hasOwn(ffmpegArgs2, "-vf")
    ? `${ffmpegArgs2["-vf"]},${parsedArgs["vf"]}`
    : parsedArgs["vf"];
}

// 要转换的视频所在目录，默认为当前目录
const sourceDir = Object.hasOwn(parsedArgs, "i") ? parsedArgs["i"] : Deno.cwd();
try {
  const stat = await Deno.lstat(sourceDir);
  if (!stat.isDirectory) {
    log(`-i 参数值 '${sourceDir}' 不是有效的目录！`);
    Deno.exit();
  }
} catch (err) {
  if (err instanceof Deno.errors.NotFound) {
    log(`-i 参数值 '${sourceDir}' 指定的目录不存在！`);
    Deno.exit();
  } else throw err;
}

// 转换的格式配置，默认为 "ts:mp4"
const t2t = (Object.hasOwn(parsedArgs, "t") ? parsedArgs["t"] : "ts:mp4").split(":");
const sourceType = t2t[0];
const targetType = t2t[1];

// 转换后的视频文件所保存的目录，默认为当前目录下的子目录 converted：
const targetDir = Object.hasOwn(parsedArgs, "o") ? parsedArgs["o"] : path.join(sourceDir, "converted");
// 创建输出目录
if (!(await exists(targetDir))) await Deno.mkdir(targetDir, { recursive: true });

log(`开始`);
log(`sourceDir=${sourceDir}`);
log(`sourceType=${sourceType}, targetType=${targetType}`);
log(`targetDir=${targetDir}`);

// 查找输入目录下匹配的视频
const sourceFiles = [];
for await (const dirEntry of Deno.readDir(sourceDir)) {
  // 仅处理匹配的视频文件
  if (dirEntry.isFile && dirEntry.name.endsWith(`.${sourceType}`)) sourceFiles.push(dirEntry.name);
}
if (sourceFiles.length === 0) {
  log("没有找到匹配的视频文件执行转换！");
  Deno.exit();
}

// 逐个视频执行转换
let i = 0;
for await (const file of sourceFiles) {
  const sourceFile = path.join(sourceDir, file);
  const targetFile = path.join(targetDir, `${path.parse(file).name}.${targetType}`);
  log(`${i + 1}/${sourceFiles.length} 开始转换 "${file}" 到 "${targetFile}"`);

  // 执行 ffmpeg 处理
  const cfg = Object.assign({}, ffmpegArgs1, { "-i": sourceFile, "_": [targetFile] }, ffmpegArgs2);
  await ffmpeg(cfg, true);

  i++;
}

log(`结束`);
